﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using ICSharpCode.AvalonEdit.Document;
using PremisPublisher.Common;
using PremisPublisher.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Input;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Client;

namespace PremisPublisher.ViewModel
{

    /*
     
     项目发布主Model
     * 
     * 作者：张鹏
     * 日期：2016.5
     
     */

    public class PublisherMainViewModel : ViewModelBase
    {
        private TextDocument _publishsContent;

        public TextDocument PublishsContent
        {
            get { return _publishsContent; }
            set { _publishsContent = value; RaisePropertyChanged("PublishsContent"); }
        }

        public ICommand SaveCommand { get; set; }
        public ICommand ReloadCommand { get; set; }
        public ICommand PublishCommand { get; set; }
        public ICommand ReBuildCommand { get; set; }
        public ICommand JsBuildCommand { get; set; }
        public ICommand XmlBuildCommand { get; set; }
        public ICommand AllActionCommand { get; set; }

        private RelayCommand _runServerScriptCommand;
        public RelayCommand RunServerScriptCommand
        {
            get
            {
                return _runServerScriptCommand ?? (_runServerScriptCommand = new RelayCommand(() =>
                {

                    string script_file = Microsoft.VisualBasic.Interaction.InputBox("输入脚本在服务器的路径（相对项目发布根目录）",
                                        "脚本路径",
                                        "",
                                        -1, -1);


                    Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "发布日志" });

                    Layer.ServiceCaller.TcpServiceDispatcher<IPRMIS_U_Contract.IPremisPublish>("0099", svc =>
                    {
                        var msg = svc.RunScript(script_file);
                        Messenger.Default.Send(new PublishLogMessage() { Message = msg });
                    });

                }));
            }
        }

        private RelayCommand _runLocalScriptCommand;
        public RelayCommand RunLocalScriptCommand
        {
            get
            {
                return _runLocalScriptCommand ?? (_runLocalScriptCommand = new RelayCommand(() =>
                {

                    System.Windows.Forms.OpenFileDialog d = new System.Windows.Forms.OpenFileDialog();


                    string filename = "";

                    if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        filename = d.FileName;
                    }
                    else return;

                    Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "发布日志" });



                    string msg = string.Empty;

                    if (!System.IO.File.Exists(filename) || string.IsNullOrEmpty(filename))
                    {
                        msg = string.Format("脚本文件 {0} 不存在", filename);
                        Messenger.Default.Send(new PublishLogMessage() { Message = msg });
                    }

                    StringBuilder sb = new StringBuilder();

                    System.Diagnostics.Process p = new System.Diagnostics.Process();
                    p.StartInfo = new System.Diagnostics.ProcessStartInfo();
                    p.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(System.Configuration.ConfigurationManager.AppSettings.Get("SourcePath"));
                    p.StartInfo.FileName = filename;
                    p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    p.StartInfo.RedirectStandardOutput = true;
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.CreateNoWindow = true;

                    p.Start();
                    p.OutputDataReceived += (a, b) =>
                    {
                        sb.AppendLine(b.Data);
                    };

                    p.BeginOutputReadLine();

                    p.WaitForExit();
                    p.Close();

                    msg = sb.ToString();

                    Messenger.Default.Send(new PublishLogMessage() { Message = msg });


                }));
            }
        }


        public PublisherMainViewModel()
        {
            PublishsContent = new TextDocument();
            PublishsContent.Text = string.Empty;
            SaveCommand = new RelayCommand(_saveCommand);
            ReloadCommand = new RelayCommand(_reloadCommand);
            PublishCommand = new RelayCommand(_publishCommand);
            ReBuildCommand = new RelayCommand(_rebuildCommand);
            JsBuildCommand = new RelayCommand(_jsBuildCommand);
            XmlBuildCommand = new RelayCommand(_xmlBuildCommand);
            AllActionCommand = new RelayCommand(_allActionCommand);

            ReloadCommand.Execute(null);

            //Messenger.Default.Register<SetMainWindowTitleMessage>(this, msg =>
            //{
            //    this.Title = msg.Message;
            //});
        }

        private void _allActionCommand()
        {
            Messenger.Default.Send(new ShowMessageDialogMessage() { Message = "请在 Visual Studio 中获取最新代码并解决冲突，确保所有代码是最新的" });

            var _reader = PublisherReader.GetInstance();
            Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "一键发布" });

            Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "正在编译" });

            BuildSol.BuildProjects(
               (line) =>
               {
                   Log( string.Format("{0}", line));
               },
               () =>
               {
                   Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "生成 JS Host 脚本" });
                   Log("编译完成, 查找Host..." );

                   var hosts = FindAllHost(_reader.SourcePath);

                   Log("\r\n开始生成 JS Host 脚本...");

                   List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();

                   System.Threading.Tasks.Task.Factory.StartNew(() =>
                   {
                       string output = PublisherReader.GetInstance().BuildOutputPath;
                       string jsHostPath = PublisherReader.GetInstance().JsHostPath;
                       output = output + "\\_PublishedWebsites\\" + jsHostPath;

                       foreach (var host_path in hosts)
                       {
                           System.Threading.Tasks.Task t = new System.Threading.Tasks.Task(() =>
                           {
                               var jshoster = new JsHoster(
                                                       host_path,
                                                       true, true,
                                                       System.IO.Path.Combine(_reader.SourcePath,
                                                       _reader.JsHostPath,
                                                       System.IO.Path.GetFileName(host_path) + ".js"), output);
                               jshoster.OnMessageShow += jshoster_OnMessageShow;
                               jshoster.AnalysisProject();
                           });

                           tasks.Add(t);
                           t.Start();
                       }

                       System.Threading.Tasks.Task.WaitAll(tasks.ToArray());

                   }).ContinueWith(r =>
                   {
                       Log("\r\nJS脚本生成完成" );
                       try
                       {
                           Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "获取最新 publish.xml 配置文件 " });

                           var analyzer = ProjectsAnalyzer.GetInstance();

                           //上传搜集到的项目信息
                           analyzer.CommitProjectFiles((s, b) =>
                           {
                               Log(string.Format("项目信息上传 {0} ", s, b ? "成功" : "失败") );
                           });

                           //获取xml文件，验证xml文件完整性
                           analyzer.GetPublishXmlContent(xmlcontent =>
                           {
                               if (string.IsNullOrEmpty(xmlcontent))
                               {
                                   Log( "未能获取 xml 配置文件，请检查配置或联系开发人员" );
                               }

                               var filename = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "publishs.xml");
                               var xsd_filename = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "publishs.xsd");

                               if (System.IO.File.Exists(filename))
                                   new System.IO.FileInfo(filename).IsReadOnly = false;

                               if (!System.IO.File.Exists(xsd_filename))
                                   Log("用于校验 xml文件的 schema 文件缺失, 请检查配置或联系开发人员" );

                               System.IO.File.WriteAllText(filename, xmlcontent, Encoding.UTF8);

                               var validate_result = ValidateXmlFile.ValidateXml(xsd_filename, filename);

                               var msg = validate_result.Equals("true") ? "构建和发布所需的配置文件下载完成并校验通过" : "配置文件错误，不能继续，请检查。";
                               Log(msg);

                           });

                           Log("\r\n重新加载配置文件 publish.xml ");

                           DispatchService.Invoke(() =>
                           {
                               if (System.IO.File.Exists(_reader.XMLPATH))
                                   PublishsContent.Text = System.IO.File.ReadAllText(_reader.XMLPATH, Encoding.UTF8);
                           });

                           Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "正在发布... " });
                           Log("正在发布...");

                           foreach (var p in _reader.Publishs)
                           {
                               p.DoPublish(x =>
                               {
                                   Log(string.Format("{0}", x.TargetPath));
                               });
                           }

                           Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "正在发布用户自定义文件 " });
                           Log("\r\n正在发布用户自定义文件...");

                           foreach (var a in _reader.Additionals)
                           {
                               a.DoPublish(x =>
                               {
                                   Log(string.Format("{0}", x.TargetPath));
                               });
                           }

                           Messenger.Default.Send(new SetLogCurrentOperationMessage() { Message = "全部文件发布完成" });
                           Log("\r\n全部文件发布完成" );

                       }
                       catch (Exception ex)
                       {
                           Messenger.Default.Send(new PublishLogMessage() { Message = ex.Message });
                       }
                   });
               });
        }

        private IEnumerable<string> FindAllHost(string s)
        {
            var dirs = System.IO.Directory.GetDirectories(s);
            Regex r = new Regex("IPRMIS_._IIS_Host");
            var q = from n in dirs where r.IsMatch(n) select n;
            return q;

        }

        /// <summary>
        /// 查找Host路径，并发生成Host的js脚本
        /// </summary>
        private void _jsBuildCommand()
        {
            var _reader = PublisherReader.GetInstance();
            Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "JS脚本生成日志" });
            Messenger.Default.Send(new PublishLogMessage() { Message = "\r\n查找Host..." });
            Messenger.Default.Send(new PublishLogMessage() { Message = "\r\n开始生成 Host 脚本..." });

            List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();

            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                string output = PublisherReader.GetInstance().BuildOutputPath;
                string jsHostPath = PublisherReader.GetInstance().JsHostPath;

                output = output + "\\_PublishedWebsites\\" + jsHostPath;

                var hosts = FindAllHost(_reader.SourcePath);

                foreach (var host_path in hosts)
                {
                    System.Threading.Tasks.Task t = new System.Threading.Tasks.Task(() =>
                    {
                        using (var jshoster = new JsHoster(host_path,
                                                true,
                                                true,
                                                System.IO.Path.Combine(_reader.SourcePath,
                                                        _reader.JsHostPath,
                                                        System.IO.Path.GetFileName(host_path) + ".js"), output))
                        {
                            jshoster.OnMessageShow += jshoster_OnMessageShow;
                            jshoster.AnalysisProject();
                        }
                    });

                    tasks.Add(t);
                    t.Start();
                }

                System.Threading.Tasks.Task.WaitAll(tasks.ToArray());

            }).ContinueWith(r =>
            {
                Messenger.Default.Send(new PublishLogMessage() { Message = "\r\nJS脚本生成完成" });
                tasks.ForEach(t => { t.Dispose(); });
            });
        }

        void jshoster_OnMessageShow(object sender, MessageEventArgs e)
        {
            Messenger.Default.Send(new PublishLogMessage() { Message = e.Message });
        }

        private void _rebuildCommand()
        {
            Messenger.Default.Send(new ShowMessageDialogMessage() { Message = "请在 Visual Studio 中获取最新代码并解决冲突，确保所有代码是最新的" });

            Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "编译日志" });

            BuildSol.BuildProjects(
                (line) =>
                {
                    Messenger.Default.Send(new PublishLogMessage() { Message = string.Format("{0}", line) });
                },
                () =>
                {
                    Messenger.Default.Send(new PublishLogMessage() { Message = "编译完成" });
                }
            );
        }

        private void _publishCommand()
        {
            Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "发布日志" });

            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                var _reader = PublisherReader.GetInstance();
                DispatchService.Invoke(() =>
                {
                    if (System.IO.File.Exists(_reader.XMLPATH)) PublishsContent.Text = System.IO.File.ReadAllText(_reader.XMLPATH, Encoding.UTF8);
                });

                foreach (var p in _reader.Publishs)
                {
                    p.DoPublish(x =>
                    {
                        Messenger.Default.Send(new PublishLogMessage() { Message = string.Format("{0}", x.TargetPath) });
                    });
                }
                Messenger.Default.Send(new PublishLogMessage() { Message = "发布完成" });
            });
        }

        private void _reloadCommand()
        {
            var _reader = PublisherReader.GetInstance();

            if (System.IO.File.Exists(_reader.XMLPATH))
                PublishsContent.Text = System.IO.File.ReadAllText(_reader.XMLPATH, Encoding.UTF8);
        }

        private void _saveCommand()
        {
            var _reader = PublisherReader.GetInstance();
            var fileContent = PublishsContent.Text;
            System.IO.File.WriteAllText(_reader.XMLPATH, fileContent, Encoding.UTF8);
            Messenger.Default.Send(new ShowMessageDialogMessage() { Message = "文件保存成功" });
        }

        private void _xmlBuildCommand()
        {
            Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "XML 构建 日志" });

            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                try
                {
                    Messenger.Default.Send(new PublishLogMessage() { Message = "\r\n上传搜集到的项目信息...\r\n" });
                    

                    var analyzer = ProjectsAnalyzer.GetInstance();

                    //上传搜集到的项目信息
                    analyzer.CommitProjectFiles((s, b) =>
                    {
                        Messenger.Default.Send(new PublishLogMessage() { Message = string.Format("项目信息上传 {0} {1} ", s, b ? "成功" : "失败") });
                    });

                    //获取xml文件，验证xml文件完整性
                    analyzer.GetPublishXmlContent(xmlcontent =>
                    {
                        if (string.IsNullOrEmpty(xmlcontent))
                        {
                            Messenger.Default.Send(new PublishLogMessage() { Message = "\r\n未能获取 xml 配置文件，请检查配置或联系开发人员" });
                        }

                        var filename = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "publishs.xml");
                        var xsd_filename = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "publishs.xsd");

                        if (System.IO.File.Exists(filename))
                            new System.IO.FileInfo(filename).IsReadOnly = false;

                        if (!System.IO.File.Exists(xsd_filename))
                            Messenger.Default.Send(new PublishLogMessage() { Message = "\r\n用于校验 xml文件的 schema 文件缺失, 请检查配置或联系开发人员" });

                        System.IO.File.WriteAllText(filename, xmlcontent, Encoding.UTF8);

                        var validate_result = ValidateXmlFile.ValidateXml(xsd_filename, filename);
                        var msg = validate_result.Equals("true") ? "\r\n构建和发布所需的配置文件下载完成并校验通过" : "\r\n配置文件错误，不能继续，请检查。";

                        Messenger.Default.Send(new PublishLogMessage() { Message = msg });

                    });
                }
                catch (Exception ex)
                {
                    Messenger.Default.Send(new PublishLogMessage() { Message = ex.Message + Environment.NewLine + ex.InnerException.Message });
                }
            });
        }


        private RelayCommand _customCpCommand;

        public RelayCommand CustomPublishCommand
        {
            get
            {
                return _customCpCommand ?? (_customCpCommand = new RelayCommand(() =>
                {
                    Messenger.Default.Send(new ShowPublishLogWindowMessage() { Message = "自定义文件发布日志" });

                    System.Threading.Tasks.Task.Factory.StartNew(() => {

                        Log("正在准备数据...");

                        var _reader = PublisherReader.GetInstance();
                        foreach (var a in _reader.Additionals)
                        {
                            a.DoPublish(x =>
                            {
                                Log(string.Format("{0}", x.TargetPath));
                            });
                        }

                        Log( "\r\n自定义文件发布完成");
                    });
                }));
            }
        }

        private RelayCommand _showStringEncryptWindowCommand;

        /// <summary>
        /// 显示字符串加密窗体
        /// </summary>
        public RelayCommand ShowStringEncryptWindowCommand
        {
            get
            {
                return _showStringEncryptWindowCommand ?? (_showStringEncryptWindowCommand = new RelayCommand(() =>
                {

                    Messenger.Default.Send(new ShowWindow() { WindowWillShow = new StringEncryptWindow() });
            
            })); }
            
        }


        private RelayCommand _getNewCodeCommand;

        public RelayCommand GetNewCodeCommand
        {
            get { return _getNewCodeCommand ?? (_getNewCodeCommand = new RelayCommand(() => {


                Messenger.Default.Send(new ShowMessageDialogMessage() {  Message = "待开发功能，敬请期待" });

            })); }
           
        }



        private void Log(string msg)
        {
            Messenger.Default.Send(new PublishLogMessage() { Message = msg });
        }
    }
}
